package com.dragon.service.impl;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPath;
import com.dragon.mapper.ContestMapper;
import com.dragon.mapper.ProblemMapper;
import com.dragon.mapper.RecordMapper;
import com.dragon.mapper.UserMapper;
import com.dragon.pojo.Problem.*;
import com.dragon.pojo.Record.Record;
import com.dragon.service.ProblemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

@Slf4j
@Service
public class ProblemServiceImpl implements ProblemService {
    // 代码文件实际路径
    @Value("${file.storage.code-path}")
    private String codePath;

    @Autowired
    private ProblemMapper problemMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RecordMapper recordMapper;
    @Autowired
    private ContestMapper contestMapper;
    @Autowired
    private UserMapper userMapper;

    @Override
    public ProblemListResult getProblemList(ProblemSelectInfo info) {
        info.setOffset((info.getPageNumber()-1)*info.getListNumber());

        List<ProblemList> problemList = problemMapper.selectProblemList(info);

        return new ProblemListResult(problemList, problemMapper.getProblemTotal(info));
    }

    @Override
    public Problem getProblemInfo(Integer problemId, Integer userId) {
        return problemMapper.getProblemInfo(problemId, userId);
    }

    @Override
    public void addProblem(Problem problem) {
        problemMapper.insertProblem(problem);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProblem(Integer problemId) {
        problemMapper.deleteProblemFromProblem(problemId);
        recordMapper.deleteProblemFromRecord(problemId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SubmitResult submit(SubmitInfo info) {
        String url = "http://127.0.0.1:8083/sandbox/run";

        SubmitTestList testList = problemMapper.getTestList(info.getProblemId());

        if(testList == null) {
            return null;
        }

        Map<String, Object> requestBody = new HashMap<>();

        // 传入参数
        requestBody.put("language", info.getLanguage());
        requestBody.put("code", info.getCode());
        requestBody.put("inputList", testList.getInputList());
        requestBody.put("outputList", testList.getOutputList());
        requestBody.put("timeLimit", testList.getTimeLimit());
        requestBody.put("memoryLimit", testList.getMemoryLimit());

        // 发送请求
        String result = restTemplate.postForObject(url, requestBody, String.class);
        SubmitResult submitResult = JSON.parseObject(result, SubmitResult.class);
        log.info(result);

        // 将源代码存入文件
        String sourceCode = (String) JSONPath.read(result, "$.sourceCode");

        // 使用UUID生成文件名
        String fileName = UUID.randomUUID() + ".txt";
        String absolutePath = codePath + fileName;
        if(!FileUtil.exist(codePath)) {
            FileUtil.mkdir(codePath);
            log.info("源代码目录不存在，创建目录: {}", codePath);
        }
        try {
            // 保存文件到目录
            Files.writeString(Paths.get(absolutePath), sourceCode);
            log.info("源代码保存成功:{}",absolutePath);
        } catch (Exception e) {
            absolutePath = "";
            log.error("源代码文件写入失败",e);
        }
        // 构建提交信息
        int completeStatus;
        int score;
        long time = 0;
        long memory = 0;

        // 计算提交信息
        if (submitResult != null) {
            completeStatus = submitResult.getSuccessTotal() >= submitResult.getTestTotal() ? 2 : 1;
            score = (submitResult.getSuccessTotal()*100) / submitResult.getTestTotal();
            List<JudgeInfo> judgeInfoList = submitResult.getJudgeInfoList();
            for (JudgeInfo judgeInfo : judgeInfoList) {
                if(judgeInfo.getRunTime() > time) {
                    time = judgeInfo.getRunTime();
                }
                if(judgeInfo.getRunMemory() > memory) {
                    memory = judgeInfo.getRunMemory();
                }
            }

            // 获取用户名
            String username = userMapper.getUsername(info.getUserId());
            // 获取题目标题
            String problemTitle = problemMapper.getProblemTitle(info.getProblemId());

            // 获取提交记录Id
            Integer recordId;
            // 封装提交信息
            if(info.getIsContest() != null && info.getIsContest()) {
                Record record = new Record(info.getProblemId(), info.getContestId(), info.getUserId(), username, problemTitle, completeStatus, score,
                        time, memory, submitResult.getFileSize(), info.getLanguage(), absolutePath, submitResult.getJudgeInfoList());
                contestMapper.addRecord(record);
                recordId = record.getId();
            } else {
                Record record = new Record(info.getProblemId(), info.getUserId(), problemTitle, completeStatus, score,
                        time, memory, submitResult.getFileSize(), info.getLanguage(), absolutePath, submitResult.getJudgeInfoList());
                recordMapper.addRecord(record);
                recordId = record.getId();
            }

            submitResult.setRecordId(recordId);
            submitResult.setScore(score);
        }


        return submitResult;
    }

    @Override
    public void updateProblem(Problem problem) {
        problemMapper.updateProblem(problem);
    }

    @Override
    public Problem getAllProblemInfo(Integer problemId) {
        return problemMapper.getAllProblemInfo(problemId);
    }

    @Override
    public String testSubmit(SubmitInfo info) {
        String url = "http://127.0.0.1:8083/sandbox/test";

        Map<String, Object> requestBody = new HashMap<>();

        // 传入参数
        requestBody.put("language", info.getLanguage());
        requestBody.put("code", info.getCode());
        List<String> inputList = new ArrayList<>();
        inputList.add(info.getInput());
        requestBody.put("input", inputList);

        // 发送请求
        String result = restTemplate.postForObject(url, requestBody, String.class);
        TestSubmitResult submitResult = JSON.parseObject(result, TestSubmitResult.class);
        log.info(result);

        if (submitResult != null) {
            return submitResult.getOutput();
        }
        return null;
    }

}
